# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="byronhulcher"
__date__ ="$Feb 17, 2011 3:08:34 PM$"


import sys, os
import random
import math,string

import pygame
from pygame import Rect

import config
from config import *

import gameobject, player, enemy, bigenemy, item, projectile
from gameobject import *
from player import *
from enemy import *
from bigenemy import *
from item import *
from projectile import *
import random

import sand
from sand import *

FULLSCREEN = True
PLAYERS = 2
SPAWNING = True
ITEM_SPAWN_RATE = 1#.3
class Game:
    # Initialization
    # Arguments:
    #     world.World world - the game world.
    def __init__(self):

        self.setup()

    def setup(self):
        pygame.init()
        random.seed()
        if FULLSCREEN:
            self.screen = pygame.display.set_mode(config.SCREEN_SIZE,pygame.FULLSCREEN|pygame.HWSURFACE)
        else:
            self.screen = pygame.display.set_mode(config.SCREEN_SIZE)
            (800,600)

        self.buffer = pygame.Surface(config.SURFACE_SIZE)
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None,16)

        self.camera = pygame.rect.Rect((0,0), config.SURFACE_SIZE)
        self.camera.center = (0,0)
        self.spritesheet = pygame.image.load(CHARACTER_SPRITESHEET)

        self.topspritesheet = pygame.image.load("top.png")
        self.itemspritesheet = pygame.image.load(ITEM_SPRITESHEET)
        self.topsprite = Surface((1024,50))
        self.topsprite.set_colorkey((0,255,255))

        self.showintro = True
        self.showgameending = False
        self.zoom = .5
        self.night = False

        self.nightswitch = 20.0

        
    def onExecute(self):
            # Intro Screen ("Press Start!")
            # Play the Game (Ends with player death
            
            
            #self.players.append(Player((200.0,0.0), self.spritesheet, (5,1)))
        while True:
            if self.showintro:
                self.menutick()
                    #self.gameovertick()
            elif self.showgameending:
                self.gameovertick(self.players)
            else:
                self._running = True
                self.players = []
                self.enemies = []
                self.items = []
                self.projectiles = []
                self.totaltime = 0
                #self.sandfactory = SandFactory()
                self.players.append(Player((1024/(PLAYERS+1.0)-512,0.0), self.spritesheet, (5,3), self.itemspritesheet))
                if PLAYERS >= 2:
                    self.players.append(Player((2*1024/(PLAYERS+1.0)-512,0.), self.spritesheet, (5,1), self.itemspritesheet))

                self.sandarray = []
                for x in range(0,1024,128):
                    for y in range (64,600,128):
                        #for i in range(1,random.randint(2,3)):
                            self.sandarray.append((random.randint(x,x+127),random.randint(y,y+127)))

                self.spawncountdown = .5-(PLAYERS*.3*random.random() + .4*(self.totaltime/120))
                tempsurf = Surface((512,25))
                tempsurf.blit(self.topspritesheet, (0,0), (random.randrange(0,1023),0,512,25))
                self.topsprite.blit(transform.scale(tempsurf, (1024,50)), (0,0))
                self.night = False
                while self._running and not self.showgameending:

                    self.clock.tick(30)
                    etime = self.clock.get_time() * 0.001
                    self.totaltime += etime
                    self.nightswitch -= etime
                    if self.nightswitch <= 0.0:
                        if self.night:
                            self.night = False
                            self.nightswitch = 5+random.random()*(20*(1-self.totaltime/120))+random.random()*10.0
                        else:
                            self.night = True
                            self.nightswitch = 3+5*random.random()+random.random()*(15*(self.totaltime/120))
                    if SPAWNING:
                        self.spawncountdown -= etime
                        if self.night:
                            self.spawncountdown -= etime*.25
                        if self.spawncountdown <= 0.0:
                            if self.night:
                                self.enemies.append(BigEnemy((random.randrange(0,1024),random.randrange(0,506)+60), self.spritesheet, self.totaltime))
                            else:
                                if random.random() < .1+(.3*(self.totaltime/180.0)):
                                    self.enemies.append(BigEnemy((random.randrange(0,1024),random.randrange(0,506)+60), self.spritesheet, self.totaltime))
                                else:
                                     self.enemies.append(Enemy((random.randrange(0,1024),random.randrange(0,506)+60), self.spritesheet, self.totaltime))
                            self.spawncountdown = 1-(.3*random.random() + .5*(self.totaltime/150))

                    self.update(etime)

                    self.drawAll(self.buffer)

                    for event in pygame.event.get():
                        self.process_event(event, etime)

                    #self.events.append(pygame.event.get())


                    self.drawBufferToScreen()
                    if PLAYERS >= 2:
                        if self.players[0].dead and self.players[1].dead:
                            self.showgameending = True
                            self.countdowntoinput = 3.0
                            #print "game should end now"
                    else:
                         if self.players[0].dead:
                            self.showgameending = True
                            self.countdowntoinput = 3.0

    def menutick(self):
        self.clock.tick(16)
        etime = self.clock.get_time() * 0.001

        if self.night == True:
            backgroundcolor = (31,31,31)
            textcolor = (196,207,161)
            textcolor2 = (139,149,109)
        else:
            backgroundcolor = (196,207,161)
            textcolor = (139,149,109)
            textcolor2 = (74,81,57)

        self.buffer.fill(backgroundcolor)
        titlerenders = [[0,0],[0,0]]
        titlefonts = [[0,0],[0,0]]
        titlefonts[0][0] = pygame.font.Font(None,random.randint(0,10)+random.randint(0,10)+40)
        titlefonts[0][1] = pygame.font.Font(None,random.randint(0,10)+random.randint(0,10)+40)
        titlefonts[1][0] = pygame.font.Font(None,random.randint(0,5)+random.randint(0,5)+30)
        titlefonts[1][1] = pygame.font.Font(None,random.randint(0,5)+random.randint(0,5)+30)
        titles = ["LEGENDS OF GRIMDARK", "Assault on Dick Mountain"]
        titlerenders[0][0] = titlefonts[0][0].render(titles[0],0,textcolor)
        titlerenders[0][0].set_alpha(200+(random.randint(0,50)))
        titlerenders[0][0] = transform.scale(titlerenders[0][0], (900,160))
        titlerenders[0][1] = titlefonts[0][1].render(titles[0],0, textcolor2)
        titlerenders[0][1].set_alpha(100+(random.randint(0,100)))
        titlerenders[0][1] = transform.scale(titlerenders[0][1],(900,160))

        titlerenders[1][0] = titlefonts[1][0].render(titles[1],0,textcolor)
        titlerenders[1][0].set_alpha(200+(random.randint(0,50)))
        titlerenders[1][0] = transform.scale(titlerenders[1][0], (600,150))
        titlerenders[1][1] = titlefonts[1][1].render(titles[1],0,textcolor2)
        titlerenders[1][1].set_alpha(100+(random.randint(0,100)))
        titlerenders[1][1] = transform.scale(titlerenders[1][1],(600,150))
        #print titles[1]
        self.buffer.blit(titlerenders[0][0],(512-(titlerenders[0][0].get_width()/2),208-(titlerenders[0][0].get_height()/2)))
        self.buffer.blit(titlerenders[0][1],(512-(titlerenders[0][1].get_width()/2),208-(titlerenders[0][1].get_height()/2)))

        self.buffer.blit(titlerenders[1][0],(512-(titlerenders[1][0].get_width()/2),348-(titlerenders[1][0].get_height()/2)))
        self.buffer.blit(titlerenders[1][1],(512-(titlerenders[1][1].get_width()/2),348-(titlerenders[1][1].get_height()/2)))
        #pressspacefont = pygame.font.Font(None,16)
        #pressspace = "press space to begin"
        #pressspacerender = pressspacefont.render(pressspace,0,(139,149,109))

        #self.buffer.blit(pressspacerender,(100-(pressspacerender.get_width()/2),125-(pressspacerender.get_height()/2)))
        if self.night:
            if random.random()< .2:
                self.night = False
        else:
            if random.random()< .03:
                self.night = True

        self.screen.blit(pygame.transform.scale(self.buffer,(1024,576)),(0,0))
        pygame.display.flip()
        for e in pygame.event.get():
            if e.type == pygame.KEYDOWN:
                self.showintro = False
            if e.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)
        
    # Updates every follower in the game.
    # Arguments:
    #     float timeSinceLastUpdate - time, in milliseconds, since the last game tick.


    def gameovertick(self, players):

        self.clock.tick(16)

        etime = self.clock.get_time() * 0.001
        self.countdowntoinput -= etime
        if self.night == False:
            backgroundcolor = (31,31,31)
            textcolor = (196,207,161)
            textcolor2 = (139,149,109)
        else:
            backgroundcolor = (196,207,161)
            textcolor = (139,149,109)
            textcolor2 = (74,81,57)

        self.buffer.fill(backgroundcolor)
        titlerenders = [[0,0],[0,0]]
        titlefonts = [[0,0],[0,0]]
        titlefonts[0][0] = pygame.font.Font(None,random.randint(0,10)+random.randint(0,10)+40)
        titlefonts[0][1] = pygame.font.Font(None,random.randint(0,10)+random.randint(0,10)+40)
        titlefonts[1][0] = pygame.font.Font(None,random.randint(0,5)+random.randint(0,5)+30)
        titlefonts[1][1] = pygame.font.Font(None,random.randint(0,5)+random.randint(0,5)+30)
        titles = ["YOU SUCK AT ADVENTURING", "FINAL SCORE: %i" % (self.players[0].score if PLAYERS < 2 else self.players[0].score+self.players[1].score)]
        titlerenders[0][0] = titlefonts[0][0].render(titles[0],0,textcolor)
        titlerenders[0][0].set_alpha(200+(random.randint(0,50)))
        titlerenders[0][0] = transform.scale(titlerenders[0][0], (900,160))
        titlerenders[0][1] = titlefonts[0][1].render(titles[0],0, textcolor2)
        titlerenders[0][1].set_alpha(100+(random.randint(0,100)))
        titlerenders[0][1] = transform.scale(titlerenders[0][1],(900,160))

        titlerenders[1][0] = titlefonts[1][0].render(titles[1],0,textcolor)
        titlerenders[1][0].set_alpha(200+(random.randint(0,50)))
        titlerenders[1][0] = transform.scale(titlerenders[1][0], (600,150))
        titlerenders[1][1] = titlefonts[1][1].render(titles[1],0,textcolor2)
        titlerenders[1][1].set_alpha(100+(random.randint(0,100)))
        titlerenders[1][1] = transform.scale(titlerenders[1][1],(600,150))
        #print titles[1]
        self.buffer.blit(titlerenders[0][0],(512-(titlerenders[0][0].get_width()/2),208-(titlerenders[0][0].get_height()/2)))
        self.buffer.blit(titlerenders[0][1],(512-(titlerenders[0][1].get_width()/2),208-(titlerenders[0][1].get_height()/2)))

        self.buffer.blit(titlerenders[1][0],(512-(titlerenders[1][0].get_width()/2),348-(titlerenders[1][0].get_height()/2)))
        self.buffer.blit(titlerenders[1][1],(512-(titlerenders[1][1].get_width()/2),348-(titlerenders[1][1].get_height()/2)))
        #pressspacefont = pygame.font.Font(None,16)
        #pressspace = "press space to begin"
        #pressspacerender = pressspacefont.render(pressspace,0,(139,149,109))


        self.screen.blit(pygame.transform.scale(self.buffer,(1024,576)),(0,0))
        pygame.display.flip()
        if self.countdowntoinput >0.0:
            return
        for e in pygame.event.get():
            if e.type == pygame.KEYDOWN:
                self.showgameending = False
                self.showintro = True
            if e.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)

    def update(self, etime):
        
        #etime /= self.timeMod

        # Real update stuff!
        #self.mouse.update(etime)
        #self.player.update(etime)
        #self.sandfactory.tick(etime)
        for player in self.players:
            player.update(etime, self.camera)
        todestroylist = []
        for i in range(len(self.enemies)):
            self.enemies[i].update(etime, self.camera, self.players, self.enemies)
            if self.enemies[i].destroyed == True:
                todestroylist.append(i)
                if (random.random() <= ITEM_SPAWN_RATE and self.enemies[i].type == "bigenemy") or (random.random() <= ITEM_SPAWN_RATE/5.0):
                    if self.enemies[i].item:
                        self.items.append(Item(self.enemies[i].position, self.itemspritesheet))
        mod = 0
        for int in todestroylist:
            del self.enemies[int+mod]
            mod -= 1

        todestroylist = []
        for i in range(len(self.items)):
            self.items[i].update(etime, self.players)
            if self.items[i].destroyed == True:
                todestroylist.append(i)
        mod = 0
        for int in todestroylist:
            del self.items[int+mod]
            mod -= 1

        todestroylist = []
        for i in range(len(self.projectiles)):
            self.projectiles[i].update(etime, self.enemies, self.players)
            if self.projectiles[i].destroyed == True:
                todestroylist.append(i)
        mod = 0
        for int in todestroylist:
            del self.projectiles[int+mod]
            #print "destroyed projectile"
            mod -= 1

    # Draws the game to the given surface
    def drawAll(self, surface):

        if self.night:
            surface.fill((31,31,31))
        else:
            surface.fill((196,207,161))
            for location in self.sandarray:
               surface.fill((139,149,109),(location[0],location[1],4,4))
        #surface.fill((74,81,57))
        
        surface.blit(self.topsprite, (0,0))
        
            
        for player in self.players:
            player.drawbottom(surface, self.camera, self.night)
        for enemy in self.enemies:
            enemy.drawbottom(surface, self.camera, self.night)
        for item in self.items:
            item.drawbottom(surface, self.night)
       
        for enemy in self.enemies:
            enemy.drawtop(surface, self.camera, self.night)
        for player in self.players:
            player.drawtop(surface, self.camera,self.night)
        for item in self.items:
            item.drawtop(surface, self.night)

        for projectile in self.projectiles:
            projectile.draw(surface)

        uifont = pygame.font.Font(None,16)
        
        text = "SCORE  %i" % self.players[0].score
        #player1score = uifont.render("SCORE-> %i" % self.players[0].score,1,(31,31,31))
        player1score = uifont.render(text,1,(31,31,31))
        player1score = transform.scale(player1score, (len(text)*20,64))
        player1score2 = uifont.render(text,1,(74,81,57))
        player1score2 = transform.scale(player1score, (len(text)*20,64))
        surface.blit(player1score2, (42,518))
        surface.blit(player1score, (40,516))

        if PLAYERS >= 2:
            text = "SCORE  %i" % self.players[1].score
            #print self.players[1].score
            player2score = uifont.render(text,1,(31,31,31))
            player2score = transform.scale(player2score, (len(text)*20,64))
            player2score2 = uifont.render(text,1,(74,81,57))
            player2score2 = transform.scale(player2score, (len(text)*20,64))
            surface.blit(player2score2, (906-player2score.get_width(),518))
            surface.blit(player2score, (904-player2score2.get_width(),516))
                #self.sandfactory.draw(surface)

        for i in range(PLAYERS):
            if len(self.players[i].itemscollected) > 25:
                del self.players[i].itemscollected[0]
            for itemnum in range(len(self.players[i].itemscollected)):
                surface.blit(transform.scale(self.players[i].itemscollected[itemnum], (16,16)), (12+(980.0*i),572-((itemnum+1)*20)))

            #pygame.draw.rect(surface, (139,149,109),((1+(1014*i),576-int(576*self.players[i].perceivedhealth/100)),(8,int(576*self.players[i].perceivedhealth/100))))
            if not self.night:
                pygame.draw.rect(surface, (31,31,31, 128),((0+(1016*i),576-int(576*self.players[i].perceivedhealth/100)),(8,int(576*self.players[i].perceivedhealth/100))))
            else:
                pygame.draw.rect(surface, (196,207,161),((0+(1016*i),576-int(576*self.players[i].perceivedhealth/100)),(8,int(576*self.players[i].perceivedhealth/100))))

            # Draws the buffer layer to the main screen
    def drawBufferToScreen(self):
        #SCALING STEP
        self.screen.blit(pygame.transform.scale(self.buffer, config.SCREEN_SIZE),(0,0))


        #fpsren = self.font.render("FPS :%i" % self.clock.get_fps(),1,(31,31,31))
        #scale = self.font.render("Scale :%f" % self.zoom,1,(31,31,31))


        #pygame.draw.rect(self.screen,(0,0,0),(0,SCREEN_SIZE[1]-22,100,22))
        #self.screen.blit(fpsren,(0,SCREEN_SIZE[1]-20))
        #self.screen.blit(scale,(0,SCREEN_SIZE[1]-10))

        pygame.display.flip()

    def process_event(self, event, etime):
        if event.type == pygame.KEYDOWN:

            if event.key == pygame.K_ESCAPE:
                self._running = False
                self.showintro = True
            elif event.key == pygame.K_a:
                self.players[0].keyMap['left'] = True
            elif event.key == pygame.K_d:
                self.players[0].keyMap['right'] = True
            elif event.key == pygame.K_w:
                self.players[0].keyMap['up'] = True
            elif event.key == pygame.K_s:
                self.players[0].keyMap['down'] = True
            elif event.key == pygame.K_j or event.key == pygame.K_LEFT :
                self.players[1].keyMap['left'] = True
            elif event.key == pygame.K_l or event.key == pygame.K_RIGHT:
                self.players[1].keyMap['right'] = True
            elif event.key == pygame.K_i or event.key == pygame.K_UP:
                self.players[1].keyMap['up'] = True
            elif event.key == pygame.K_k or event.key == pygame.K_DOWN:
                self.players[1].keyMap['down'] = True
            elif event.key == pygame.K_r:
                self.players[0].keyMap['attack'] = True
                if self.players[0].attackcountdown <= 0.0:
                    direction = self.players[0].lastdirection
                    directionradians = ((.5*math.pi)+(math.pi/4)*direction)
                    self.projectiles.append(Projectile(self.players[0].directionsprites[self.players[0].frame][self.players[0].lastdirection], (self.players[0].dirmarkpositions[self.players[0].lastdirection][0]+16,self.players[0].dirmarkpositions[self.players[0].lastdirection][1]+16), 0, self.players[0].damage, directionradians, self.players[0].attackspeed))
                    self.players[0].attackcountdown = self.players[0].attackrate
                    #print " Player created projectile at", self.players[0].position
            elif event.key == pygame.K_y or event.key == pygame.K_p:
                self.players[1].keyMap['attack'] = True
                if self.players[1].attackcountdown <= 0.0:
                    direction = self.players[1].lastdirection
                    directionradians = ((.5*math.pi)+(math.pi/4)*direction)
                    self.projectiles.append(Projectile(self.players[1].directionsprites[self.players[1].frame][self.players[1].lastdirection], (self.players[1].dirmarkpositions[self.players[1].lastdirection][0]+12,self.players[1].dirmarkpositions[self.players[1].lastdirection][1]+12), 1, self.players[1].damage, directionradians, self.players[1].attackspeed))
                    self.players[1].attackcountdown = self.players[1].attackrate
                    #print " Player created projectile at", self.players[1].position
            elif event.key == pygame.K_z:
                self.night = not self.night
           
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                self.players[0].keyMap['left'] = False
            elif event.key == pygame.K_d:
                self.players[0].keyMap['right'] = False
            elif event.key == pygame.K_w:
                self.players[0].keyMap['up'] = False
            elif event.key == pygame.K_s:
                self.players[0].keyMap['down'] = False
            elif event.key == pygame.K_j or event.key == pygame.K_LEFT :
                self.players[1].keyMap['left'] = False
            elif event.key == pygame.K_l or event.key == pygame.K_RIGHT :
                self.players[1].keyMap['right'] = False
            elif event.key == pygame.K_i or event.key == pygame.K_UP :
                self.players[1].keyMap['up'] = False
            elif event.key == pygame.K_k or event.key == pygame.K_DOWN:
                self.players[1].keyMap['down'] = False
            elif event.key == pygame.K_r or event.key == pygame.K_p:
                self.players[0].keyMap['attack'] = False
            elif event.key == pygame.K_z:
                pass

        if event.type == MOUSEBUTTONDOWN:
            #print event.button
            #self.items.append(Item((pygame.mouse.get_pos()[0]-512,pygame.mouse.get_pos()[1]-288), self.itemspritesheet))
            #self.enemies.append(Enemy((pygame.mouse.get_pos()), self.spritesheet))
            if random.random() < .1:
                self.enemies.append(BigEnemy((pygame.mouse.get_pos()), self.spritesheet, self.totaltime))
            else:
                self.enemies.append(Enemy((pygame.mouse.get_pos()), self.spritesheet, self.totaltime))
           
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit(0)

if __name__ == "__main__":
    myGame = Game()
    myGame.onExecute()

